<?php
/**
 * @file
 * Implements all assignment related services.
 */

/**
 * Loads a node and parses its assignment field.
 */
function _get_assignments($node) {
  try {
    $element = new SimpleXMLElement($node->assignment);
  }
  catch (Exception $e) {
    var_dump($node);
    var_dump($node->signup);
    var_dump($e);
  }
  return $element;
}

/**
 * Saves the assignments after manipulation
 */
function _save_assignments(SimpleXMLElement $element, $node) {
  try {
    $node->assignment = $element->asXML();
    node_save($node);
  }
  catch (Exception $e) {
    var_dump($e);
    var_dump($node);
  }
}

/**
 * @return The number of unassigned users.
 */
function _automatic_assign(SimpleXMLElement $signups, SimpleXMLElement $assignments, SimpleXMLElement $config) {
  $unassigned = 0;
  foreach ($signups->user as $user) {
    $assigned = false;
    if (!_is_already_assigned($assignments, $user->name)) {
        $boatId = _get_boatselect_id($user);
	    if ($boatId) {
	        $assigned = _assign_user_to_boat($assignments, $config, (String) $user->name, $boatId);
	    }
	    if (!$assigned) $unassigned++;
    }
  }
  return $unassigned;
}

function _assign_user_to_boat(SimpleXMLElement $assignments, SimpleXMLElement $config, $name, $boatId) {
  $boat = _get_or_create_boat($assignments, $boatId);
  if (!_is_boat_fully_occupied($config, $boat)) {
    $signup = $boat->addChild("signup");
    $signup->addAttribute("user", $name);
    return true;
  } else {
    return false;
  }
}

function _remove_user_from_boat(SimpleXMLElement $assignments, $name, $boatId) {
  $doc = new DOMDocument;
  $doc->loadXML($assignments->asXML());
  $root = $doc->documentElement;
  $boats = $doc->getElementsByTagName("boat");
  foreach ($boats as $boat) {
    if ($boat->getAttribute("id") == $boatId) {
      $signups = $boat->getElementsByTagName("signup");
      foreach ($signups as $signup) {
        if ($signup->getAttribute("user") == $name) {
          $boat->removeChild($signup);
          break; 
        }
      }
    }
  }
  $assignments = new SimpleXMLElement($doc->saveXML());
  return $assignments;
}

function _get_or_create_boat(SimpleXMLElement $assignments, $boatId) {
  $boat = _get_boat_assignments_by_id($assignments, $boatId);
  if ($boat == null) {
    return _create_boat($assignments, $boatId);
  } else {
    return $boat;
  }
}

function _get_boat_assignments_by_id(SimpleXMLElement $assignments, $boatId) {
  $xpath = "//boat[@id='".$boatId."']";
  $result = $assignments->xpath($xpath);
  if ($result === FALSE) return FALSE;
  else if (sizeof($result) == 0) return null;
  else if (sizeof($result) > 1) throw new Exception("More than 1 boat with id $boatId");
  else return $result[0];
}

function _create_boat(SimpleXMLElement $assignments, $boatId) {
  $boat = $assignments->addChild("boat");
  $boat->addAttribute("id", $boatId);
  return $boat;
}

function _get_number_of_signups(SimpleXMLElement $boat) {
  $xpath = "//boat[@id='".(String)$boat["id"]."']/signup";
  $result = $boat->xpath($xpath);
  if ($result === FALSE) return FALSE;
  else return sizeof($result);
}

function _is_boat_fully_occupied(SimpleXMLElement $config, SimpleXMLElement $boat) {
  $boatConfig = _get_boat_config_by_id($config, (String) $boat['id']);
  return (int)_get_number_of_signups($boat) >= (int) $boatConfig["places"];
}

function _is_already_assigned(SimpleXMLElement $assignments, $userName) {
  $xpath = "//signup[@user='".$userName."']";
  $result = $assignments->xpath($xpath);
  if ($result === FALSE) return FALSE;
  else return (sizeof($result) > 0);
}

function _delete_assignments_of_user(SimpleXMLElement $assignments, $userName) {
  $doc = new DOMDocument;
  $doc->loadXML($assignments->asXML());
  $root = $doc->documentElement;
  $boats = $doc->getElementsByTagName("boat");
  foreach ($boats as $boat)
  { 
    $assignmentElements = $boat->getElementsByTagName("signup");
    foreach ($assignmentElements as $assignmentElement) {
      if ($assignmentElement->getAttribute("user") == $userName) {
        $boat->removeChild($assignmentElement);
        break;
      }
    }
  }
  $element = new SimpleXMLElement($doc->saveXML());
  return $element;
}

function _get_unassigned_users(SimpleXMLElement $signups, SimpleXMLElement $assignments) {
  $unassigned = array();
  foreach ($signups->user as $user)  {
    if (!_is_already_assigned($assignments, (String)$user->name)) {
      $unassigned[] = $user;
    }
  }
  return $unassigned;
}

/**
 * @return Array of SimpleXMLObjects (boat-element from assignments)
 */
function _get_boats_with_free_places(SimpleXMLElement $config, SimpleXMLElement $assignments) {
  $boats = array();
  foreach (_get_boats($config) as $boatConfig) {
    $boat = _get_or_create_boat($assignments, (String) $boatConfig["id"]);
    if (!_is_boat_fully_occupied($config, $boat)) {
      $boats[] = $boat;
    }
  }
  return $boats;
}

function _get_assignments_by_boatid(SimpleXMLElement $assignments, $boatId) {
  $xpath = "//boat[@id='$boatId']/signup";
  $result = $assignments->xpath($xpath);
  if ($result === FALSE) return array();
  else return $result;
}

function _remove_unfixed_assignments(SimpleXMLElement $assignments) {
  foreach ($assignments->boat as $boat) {
    foreach ($boat->signup as $signup) {
	    if (!$signup['fixed'] == "true") {
	      $assignments = _remove_user_from_boat($assignments, $signup['user'], $boat['id']);
	    }
    }
  }
  return $assignments;
}